/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package compiledriver;

import java.util.HashMap;
import java.util.ListIterator;
import java.util.Map;

/**
 *
 * @author wynd
 *
 * <p>An <code>Operation</code> class that extends the <code>Definition</code>
 * class. Definition with ensures and requires clauses.</p>
 */
public class Operation extends Definition {

    protected Expression requiresExpr;
    protected Expression ensuresExpr;
    
    
    /**
     * Creates an <code>Operation</code> that contains a required and ensures
     * clause
     * 
     * @param intext tokens an Iterator to the requires and ensures clauses
     * @throws IllegalStateException if a definition that doesn't exist is used
     * and/or if is uses a definition with wrong number of arguments.</p>
     */
    public Operation (ListIterator<String> intext, 
            HashMap<String, Definition> defHash)

    {
        super(intext);
        requiresExpr = new Expression(intext);
        defTest(requiresExpr, defHash);
        ensuresExpr = new Expression(intext);
        defTest(ensuresExpr, defHash);
    }
    
    private void defTest(Expression expr, Map<String, Definition> defHash)
    {
        if (expr.isFunction)
        {
            Definition reqDef = defHash.get(expr.getId());
            if (reqDef != null)
            {
                if (reqDef.argList.size() != expr.myArguments.size())
                {
                    throw new IllegalStateException(expr.getId() 
                            + " was called with the wrong number of arguments: " 
                            + expr.myArguments.size() + "\n should be: " 
                            + reqDef.argList.size());
                }
            }
            else
            {
                throw new IllegalStateException("Did not find " 
                        + expr.getId() + " in the declared Definitions");
            }
            for (Expression e: expr.myArguments)
            {
                defTest(e, defHash);
            }
        }
    }

     /**
     * <p>Returns the requires clause of <code>Operation</code> as an
     * <code>Expression</code>
     * @return returns the required clause 
     */
    public Expression getRequires(){
        return requiresExpr;
        
    }
    
    /**
     * <p>Returns the ensures clause of<code>Operation</code> as an
     * <code>Expression</code>
     * @return returns the ensures clause</p>
     */
    public Expression getEnsures(){
        return ensuresExpr;
    }
    
    /**
     * 
     * @return <p>returns a <code>String</code> value of the requires and
     * ensures clauses</p>
     */
    @Override
    public String toString(){
        String returningString = super.toString();
        
        returningString += "\nrequires:  " + requiresExpr;
        returningString += "\nensures:  " + ensuresExpr;
        
        return returningString;   
        
    }
}
